package com.societyGames.flashForms
{
import com.societyGames.system.EventObject;

import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;

/**
 * Stores children nodes of a node.
 */
public class TreeViewContainer extends Sprite implements IChangeSize
{
  private var _nodes:Vector.<DisplayObject> = new Vector.<DisplayObject>();
  private var _sizeChangedEventObject:EventObject;
  private var _isExpanded:Boolean = true;
  private var _desiredHeight:Number;
  private var _desiredWidth:Number;

  public function TreeViewContainer()
  {
    this._sizeChangedEventObject = new EventObject(this, "SIZE_CHANGED");
  }

  public override function set width(value:Number):void
  {
    this._desiredWidth = value;
  }

  public override function set height(value:Number):void
  {
    this._desiredHeight = value;
  }

  public function get sizeChangedEventObject():EventObject
  {
    return this._sizeChangedEventObject;
  }

  public function get nodeCount():int
  {
    return this._nodes.length;
  }

  public function addNode(displayObject:DisplayObject):void
  {
    this._nodes.push(displayObject);
    var changeSize:IChangeSize = displayObject as IChangeSize;
    if (changeSize != null)
    {
      changeSize.sizeChangedEventObject.addEventListener(nodeSizeChanged);
    }
    if (this._isExpanded)
    {
      if (this._nodes.length > 1)
      {
        var previous:DisplayObject = DisplayObject(this._nodes[this._nodes.length - 2]);
        displayObject.y = previous.y + previous.height;
      }
      else
      {
        displayObject.y = 0;
      }
      this.addChild(displayObject);
      this._sizeChangedEventObject.dispatchEvent();
    }
  }

  public function removeNode(displayObject:DisplayObject):void
  {
    var index:int = this._nodes.indexOf(displayObject);
    if (index != -1)
    {
      this._nodes.splice(index, 1);
      var changeSize:IChangeSize = displayObject as IChangeSize;
      if (changeSize != null)
      {
        changeSize.sizeChangedEventObject.removeEventListener(nodeSizeChanged);
      }
      if (this._isExpanded)
      {
        this.removeChild(displayObject);
        var nextY:Number = displayObject.y;
        for (var i:int = index; i < this._nodes.length; i++)
        {
          this._nodes[i].y = nextY;
          nextY += this._nodes[i].height;
        }
        this._sizeChangedEventObject.dispatchEvent();
      }
    }
  }

  public function clear():void
  {
    for each (var displayObject:DisplayObject in this._nodes)
    {
      var changeSize:IChangeSize = displayObject as IChangeSize;
      if (changeSize != null)
      {
        changeSize.sizeChangedEventObject.removeEventListener(nodeSizeChanged);
      }
      this.removeChild(displayObject);
    }
    this._nodes.length = 0;
    this._sizeChangedEventObject.dispatchEvent();
  }

  public function get isExpanded():Boolean
  {
    return this._isExpanded;
  }

  public function set isExpanded(value:Boolean):void
  {
    if (this._isExpanded != value)
    {
      this._isExpanded = value;
      if (this._isExpanded)
      {
        //Add the elements in.
        var nextY:Number = 0;
        for (var addIndex:int = 0; addIndex < this._nodes.length; addIndex++)
        {
          var addDisplayObject:DisplayObject = this._nodes[addIndex];
          addDisplayObject.y = nextY;
          this.addChild(addDisplayObject);
          nextY += addDisplayObject.height;
        }
      }
      else
      {
        //Clear
        for (var removeIndex:int = 0; removeIndex < this._nodes.length; removeIndex++)
        {
          this.removeChild(this._nodes[removeIndex]);
        }
      }
      this._sizeChangedEventObject.dispatchEvent(); //TODO: this might not need to be raised if there are no nodes.
    }
  }

  private function nodeSizeChanged(event:Event):void
  {
    var index:int = this._nodes.indexOf(event.target);
    for (index++; index < this._nodes.length; index++)
    {
      this._nodes[index].y = this._nodes[index - 1].y + this._nodes[index - 1].height;
    }
    this._sizeChangedEventObject.dispatchEvent();
  }
}
}